#pragma once
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace std;
const string nullPath = "/dev/null";

void deamonize(const string& cwd = "")
{
    pid_t pid;
    // 1. 忽略其它异常信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGSTOP, SIG_IGN);

    // 2. 让其变成一个独立的会话
    if((pid = fork()) < 0) {
        printf("创建子进程失败!\n");
        return;
    } else if(pid > 0)    exit(0);
    setsid();
    // printf("after setsid()\n");
    // 3. 更改工作目录(可选)
    if(cwd != "") {
        if(chdir(cwd.c_str()) < 0) {
            printf("更改目录失败!\n");
            return;
        }
    }

    /*
    4. 将标准输入，标准输出，标准错误重定向到nullPath
    这样，任何一个试图读标准输入，写标准输出或标准错误的库例程都不会产生任何效果。
    因为守护进程不与终端设备相关联，所以其输出无从显示，也无处从交互式用户那里产生任何效果
    */ 
    int fd = open(nullPath.c_str(), O_RDWR);
    if(fd > 0) {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    } else {
        printf("打开nullPath失败\n");
        return;
    }
}
